package com.yupi.yupicturebackend.api.deepseek;

import com.fasterxml.jackson.databind.JsonNode;
import com.yupi.yupicturebackend.api.deepseek.model.DeepseekRequest;
import com.yupi.yupicturebackend.api.deepseek.model.Message;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import okio.BufferedSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class DeepseekApi {
    @Value("${deepseek.api.key}")
    private String apiKey;
    @Value("${deepseek.api.url}")
    private String apiUrl;

    private final OkHttpClient client;
    private final ObjectMapper objectMapper;

    public DeepseekApi() {
        this.client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build();
        this.objectMapper = new ObjectMapper();
    }

    private static final String PROMPT_TEMPLATE =
            "你是一位专业的历史文化科普专家，请对以下地点进行详细、准确的科普介绍，要求：\n\n" +
                    "1. 首先用1-2句话简要概括该地点的核心特征\n" +
                    "2. 然后分多个方面系统介绍：\n" +
                    "   - 历史背景（建造时间、历史意义）\n" +
                    "   - 建筑/景观特色（主要特点、设计风格）\n" +
                    "   - 文化价值（在文化史上的地位）\n" +
                    "   - 重要事件（与该地点相关的历史大事）\n" +
                    "   - 现状情况（当前状态、保护级别等）\n" +
                    "3. 语言风格：专业严谨但通俗易懂，避免过于学术化\n" +
                    "4. 字数控制在300-500字之间\n" +
                    "5. 最后提供1-2个关于该地点的有趣冷知识\n\n" +
                    "请科普的地点：%s";



    private static final String IMAGE_SEARCH_PROMPT_TEMPLATE =
            "你是一个专业的图像搜索语义分析助手，请将以下中文描述（可能是现代语言或古诗词）解析为适合图像搜索的关键词组合。要求：\n\n" +
                    "1. 首先理解文本的核心意象和主题\n" +
                    "2. 提取3-5个最相关的视觉关键词（中文）\n" +
                    "3. 如果是古诗词，需解析其描绘的视觉场景\n" +
                    "4. 关键词之间用逗号分隔\n" +
                    "5. 只返回关键词，不要任何解释\n\n" +
                    "需要解析的文本：%s";

//    /**
//     * 流式调用 DeepSeek API
//     * @param locationName 地点名称
//     */
//    public void streamChatResponse(String locationName, SseEmitter emitter) throws IOException {
//        String prompt = String.format(PROMPT_TEMPLATE, locationName);
//        extracted(emitter, prompt, "knowledge");
//    }


//    /**
//     * 流式处理图片搜索的自然语言解析
//     * @param userQuery 用户输入的自然语言（现代语言或古诗词）
//     */
//    public void streamImageSearchKeywords(String userQuery, SseEmitter emitter) throws IOException {
//        String prompt = String.format(IMAGE_SEARCH_PROMPT_TEMPLATE, userQuery);
//        extracted(emitter, prompt, "image_search");
//    }


    // 封装出来 避免重复代码 其他地方可以直接复用 只需要更换自己的提示词即可  这里是传地点名称
//    private String  extracted(SseEmitter emitter, String prompt, String scenario) throws IOException {
//        // 使用对象构建请求体
//        DeepseekRequest requestBody = new DeepseekRequest();
//        requestBody.setModel("deepseek-chat");
//        requestBody.setMessages(Collections.singletonList(
//                new Message("user", prompt)
//        ));
//        // 根据场景设置不同参数
//        switch (scenario) {
//            case "knowledge":
//                requestBody.setTemperature(1.0);
//                requestBody.setMax_tokens(2048);
//                requestBody.setStream(true);
//                break;
//            case "image_search":
//                requestBody.setTemperature(0.7);
//                requestBody.setMax_tokens(1024);
//                requestBody.setStream(false);
//                break;
//            default:
//                requestBody.setTemperature(0.8);
//                requestBody.setMax_tokens(1536);
//                requestBody.setStream(true);
//        }
//
//        // 转换为JSON
//        String jsonBody = objectMapper.writeValueAsString(requestBody);
//
//        Request request = new Request.Builder()
//                .url(apiUrl)
//                .post(RequestBody.create(jsonBody, MediaType.parse("application/json")))
//                .addHeader("Authorization", "Bearer " + apiKey)
//                .addHeader("Content-Type", "application/json") // 必须添加
//                .addHeader("Accept", "text/event-stream")
//                .build();
//
//        // 执行请求
//        try (Response response = client.newCall(request).execute()) {
//            if (!response.isSuccessful()) {
////                throw new IOException("Unexpected code " + response + ", body: " +
////                        (response.body() != null ? response.body().string() : "null"));
//                emitter.send(SseEmitter.event()
//                        .name("error")
//                        .data("API请求失败: " + response.code()));
//                emitter.complete();
//                return null;
//            }
//
//            try (ResponseBody body = response.body()) {
//                if (body != null) {
////                    processStreamResponse(body.source());
//                    if (scenario.equals("image_search")) {
//                        JsonNode rootNode = objectMapper.readTree(body.string());
//                        return rootNode.path("choices").get(0).path("message").path("content").asText();
//                    }
//                    BufferedSource source = body.source();
//                    while (!source.exhausted()) {
//                        String line = source.readUtf8Line();
//                        if (line == null) continue;
//
//                        if (line.startsWith("data: ")) {
//                            String data = line.substring(6).trim();
//                            if (data.equals("[DONE]")) {
//                                emitter.send(SseEmitter.event()
//                                        .name("complete")
//                                        .data("流式响应结束"));
//                                break;
//                            }
//
//                            String content = extractContentFromJson(data);
//                            if (!content.isEmpty()) {
//                                // 由于流式响应中 回车换行 被消耗为空的行 导致前端无法正常解析回车换行
//                                // 所以直接把 \n 替换成 \x0A  这样空的行就变成了字符串 \x0A 前端在去转换回\n即可
//                                // 这里会把如### 标题 替换成 ###&nbsp;标题&nbsp;  前端解析时 就会有问题
//                                String replace = content.replace("\n", "\\x0A").replace(" ", "&nbsp;");
//                                emitter.send(SseEmitter.event()
//                                        .name("message")
//                                        .data(replace));
//                            }
//                        }
//                    }
//                    emitter.complete();
//                }
//            }
//        }
//        return null;
//    }

    /**
     * 处理流式响应
     */
//    private void processStreamResponse(BufferedSource source) throws IOException {
//        while (!source.exhausted()) {
//            String line = source.readUtf8Line();
//            /**
//             * data: {"choices": [{"delta": {"content": "故宫是明清两代的皇家宫殿"}}]}
//             * data: {"choices": [{"delta": {"content": "它始建于永乐年间"}}]}
//             * data:
//             * data: [DONE]
//             *
//             * 这个判断就是在遇到data为空时 直接跳过
//             */
//            if (line == null) continue;
//
//            if (line.startsWith("data: ")) {
//                String data = line.substring(6).trim();
//                if (data.equals("[DONE]")) {
//                    System.out.println("\n流式响应结束");
//                    break;
//                }
//
//                System.out.print(extractContentFromJson(data));
//            }
//        }
//    }

    /**
     * 从 JSON 数据中提取内容
     */
    private String extractContentFromJson(String json) throws IOException {
        // 使用 Jackson 解析 JSON
        JsonNode rootNode = objectMapper.readTree(json);
        JsonNode choices = rootNode.path("choices");
        if (choices.isArray() && choices.size() > 0) {
            JsonNode delta = choices.get(0).path("delta");
            if (delta.has("content")) {
                return delta.get("content").asText();
            }
        }
        return "服务繁忙，请稍候重试！";
    }







    /**
     * 处理流式响应场景(knowledge)
     */
    private void handleStreamResponse(SseEmitter emitter, String prompt) throws IOException {
        DeepseekRequest requestBody = createRequest(prompt, "knowledge");

        Request request = new Request.Builder()
                .url(apiUrl)
                .post(RequestBody.create(objectMapper.writeValueAsString(requestBody),
                        MediaType.parse("application/json")))
                .addHeader("Authorization", "Bearer " + apiKey)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "text/event-stream")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                emitter.send(SseEmitter.event()
                        .name("error")
                        .data("API请求失败: " + response.code()));
                emitter.complete();
                return;
            }

            try (ResponseBody body = response.body()) {
                if (body != null) {
                    BufferedSource source = body.source();
                    while (!source.exhausted()) {
                        String line = source.readUtf8Line();
                        if (line == null) continue;

                        if (line.startsWith("data: ")) {
                            String data = line.substring(6).trim();
                            if (data.equals("[DONE]")) {
                                emitter.send(SseEmitter.event()
                                        .name("complete")
                                        .data("流式响应结束"));
                                break;
                            }

                            String content = extractContentFromJson(data);
                            if (!content.isEmpty()) {
                                String replace = content.replace("\n", "\\x0A").replace(" ", "&nbsp;");
                                emitter.send(SseEmitter.event()
                                        .name("message")
                                        .data(replace));
                            }
                        }
                    }
                    emitter.complete();
                }
            }
        }
    }

    /**
     * 处理非流式响应场景(image_search)
     */
    private String handleNonStreamResponse(String prompt) throws IOException {
        DeepseekRequest requestBody = createRequest(prompt, "image_search");

        Request request = new Request.Builder()
                .url(apiUrl)
                .post(RequestBody.create(objectMapper.writeValueAsString(requestBody),
                        MediaType.parse("application/json")))
                .addHeader("Authorization", "Bearer " + apiKey)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("API请求失败: " + response.code());
            }

            try (ResponseBody body = response.body()) {
                if (body != null) {
                    JsonNode rootNode = objectMapper.readTree(body.string());
                    return rootNode.path("choices").get(0).path("message").path("content").asText();
                }
                throw new IOException("Empty response body");
            }
        }
    }

    /**
     * 创建请求参数
     */
    private DeepseekRequest createRequest(String prompt, String scenario) {
        DeepseekRequest requestBody = new DeepseekRequest();
        requestBody.setModel("deepseek-chat");
        requestBody.setMessages(Collections.singletonList(new Message("user", prompt)));

        switch (scenario) {
            case "knowledge":
                requestBody.setTemperature(1.0);
                requestBody.setMax_tokens(2048);
                requestBody.setStream(true);
                break;
            case "image_search":
                requestBody.setTemperature(0.7);
                requestBody.setMax_tokens(1024);
                requestBody.setStream(false);
                break;
            default:
                requestBody.setTemperature(0.8);
                requestBody.setMax_tokens(1536);
                requestBody.setStream(true);
        }
        return requestBody;
    }

    /**
     * 对外暴露的方法
     */
    public void streamChatResponse(String locationName, SseEmitter emitter) throws IOException {
        String prompt = String.format(PROMPT_TEMPLATE, locationName);
        handleStreamResponse(emitter, prompt);
    }

    public List<String> parseImageSearchKeywords(String userQuery) throws IOException {
        String prompt = String.format(IMAGE_SEARCH_PROMPT_TEMPLATE, userQuery);
        String response = handleNonStreamResponse(prompt);
        return Arrays.stream(response.split(","))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .collect(Collectors.toList());
    }

}